home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
util
/
gnu
/
emacs_src.lha
/
emacs-18.58
/
src
/
amiga_rexx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-16
|
7KB
|
241 lines
#include "SimpleRexx.h"
#include <proto/exec.h>
#undef NULL
#include "config.h"
#include "lisp.h"
#include "amiga.h"
static AREXXCONTEXT far handle;
#define REXXSIZE 32
static struct {
int rc; /* 0 for commands, <> 0, for errors */
union {
struct { int id; int code; } error; /* Of failed messages */
struct RexxMsg *msg; /* Received command */
} u;
} pending_rexx_msgs[REXXSIZE];
static int pending_rexx_num, pending_rexx_in, pending_rexx_out;
static int amiga_arexx_initialized;
static struct {
struct RexxMsg *msg;
int id;
} sent_rexx_msg[REXXSIZE];
static int sent_rexx_id;
int check_arexx(int force, int kbd)
{
struct RexxMsg *rmsg;
int msg_received = FALSE;
while (rmsg = GetARexxMsg(handle))
{
msg_received = TRUE;
if (rmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
{
int i;
/* The message has been returned, remove it from sent messages */
for (i = 0; i < REXXSIZE && sent_rexx_msg[i].msg != rmsg; i++) ;
if (i < REXXSIZE) sent_rexx_msg[i].msg = 0;
if (rmsg->rm_Result1)
{
/* There was an error, add it to pending_rexx_msgs */
if (pending_rexx_num != REXXSIZE)
{
pending_rexx_num++;
pending_rexx_msgs[pending_rexx_in].u.error.id =
i < REXXSIZE ? sent_rexx_msg[i].id : 0;
pending_rexx_msgs[pending_rexx_in].u.error.code = rmsg->rm_Result2;
pending_rexx_msgs[pending_rexx_in].rc = rmsg->rm_Result1;
pending_rexx_in = (pending_rexx_in + 1) % REXXSIZE;
}
/* else ignore this error */
}
DeleteARexxMsg(handle, rmsg);
}
else
{
if (pending_rexx_num == REXXSIZE)
{
/* Oops! Throw out message */
SetARexxLastError(handle, rmsg, "Emacs too busy");
ReplyARexxMsg(handle, rmsg, 0, 20);
}
else
{
pending_rexx_num++;
pending_rexx_msgs[pending_rexx_in].u.msg = rmsg;
pending_rexx_msgs[pending_rexx_in].rc = 0;
pending_rexx_in = (pending_rexx_in + 1) % REXXSIZE;
}
}
}
if (kbd && amiga_arexx_initialized && (msg_received || force && pending_rexx_num > 0))
{
enque(AMIGASEQ, FALSE); enque('X', FALSE);
}
return msg_received;
}
DEFUN ("amiga-arexx-wait", Famiga_arexx_wait, Samiga_arexx_wait, 0, 0, 0,
"Wait for an ARexx event (command or reply) before proceeding.")
()
{
while (!check_arexx(FALSE, FALSE)) Wait(ARexxSignal(handle));
}
DEFUN ("amiga-arexx-check-command",
Famiga_arexx_check_command, Samiga_arexx_check_command, 1, 1, 0,
"Return t if command ID has finished, nil otherwise.")
(id)
{
int i, nid;
CHECK_NUMBER (id, 0);
nid = XUINT (id);
for (i = 0; i < REXXSIZE && (!sent_rexx_msg[i].msg || nid != sent_rexx_msg[i].id);
i++) ;
return i == REXXSIZE ? Qnil : Qt;
}
DEFUN ("amiga-arexx-get-event", Famiga_arexx_get_event, Samiga_arexx_get_event,
0, 0, 0,
"Returns next arexx event, either an error or a command to execute.\n\
If no event is waiting, nil is returned.\n\
Errors are returned as a (id-of-failed-command severity error-code) list\n\
(Don't answer these events!).\n\
Commands are strings sent by an arexx process. They should be answered via\n\
amiga-arexx-reply. amiga-arexx-get-event will always return the same command\n\
till you do so.")
()
{
struct RexxMsg *rmsg;
check_arexx(FALSE, FALSE);
if (pending_rexx_num)
if (pending_rexx_msgs[pending_rexx_out].rc)
{
Lisp_Object id, error, rc;
Lisp_Object res;
XSET (id, Lisp_Int, pending_rexx_msgs[pending_rexx_out].u.error.id);
XSET (error, Lisp_Int,
pending_rexx_msgs[pending_rexx_out].u.error.code & VALMASK);
XSET (rc, Lisp_Int, pending_rexx_msgs[pending_rexx_out].rc & VALMASK);
res = Fcons (id, Fcons (rc, Fcons (error, Qnil)));
pending_rexx_out = (pending_rexx_out + 1) % REXXSIZE;
pending_rexx_num--;
return res;
}
else return build_string(ARG0(pending_rexx_msgs[pending_rexx_out].u.msg));
return Qnil;
}
DEFUN ("amiga-arexx-reply", Famiga_arexx_reply, Samiga_arexx_reply,
2, 2, 0,
"Replies to the first arexx message (the one got via amiga-arexx-get-event)\n\
with RC as return code.\n\
If RC=0, TEXT is the result, otherwise it is the error text. It can be nil.")
(rc, text)
{
int retcode;
char *result;
struct RexxMsg *rmsg;
int ok = TRUE;
if (!pending_rexx_num) error("No ARexx message to reply to.");
CHECK_NUMBER(rc, 0);
retcode = XINT(rc);
if (!NULL (text))
{
CHECK_STRING(text, 0);
result = XSTRING (text)->data;
}
else result = 0;
if (pending_rexx_msgs[pending_rexx_out].rc)
error("You can't answer an error !");
rmsg = pending_rexx_msgs[pending_rexx_out].u.msg;
pending_rexx_out = (pending_rexx_out + 1) % REXXSIZE;
pending_rexx_num--;
if (retcode && result)
ok = SetARexxLastError(handle, rmsg, result);
ReplyARexxMsg(handle, rmsg, result, retcode);
if (!ok) error("Failed to set ARexx error message.");
return Qnil;
}
DEFUN ("amiga-arexx-send-command", Famiga_arexx_send_command, Samiga_arexx_send_command,
1, 2, "sARexx command: \n\
P",
"Sends a command to ARexx for execution.\n\
If the second arg is non-nil, the command is directly interpreted.\n\
Returns an integer that uniquely identifies this message (for use in ???).")
(str, as_file)
{
struct ARexxMsg *rmsg;
int i;
Lisp_Object id;
/* Find a free slot for message */
for (i = 0; i < REXXSIZE && sent_rexx_msg[i].msg; i++) ;
if (i == REXXSIZE) error("Too many arexx commands pending (max %d)", REXXSIZE);
CHECK_STRING (str, 0);
if (!(rmsg = SendARexxMsg(handle, XSTRING (str)->data, !NULL (as_file))))
error("Failed to send command to ARexx.");
sent_rexx_msg[i].msg = rmsg;
sent_rexx_id = (sent_rexx_id + 1) & VALMASK;
sent_rexx_msg[i].id = sent_rexx_id;
XSET (id, Lisp_Int, sent_rexx_id);
return id;
}
void init_amiga_rexx(void)
{
extern ULONG inputsig;
int i;
handle = InitARexx("Emacs", "elx");
inputsig |= ARexxSignal(handle);
pending_rexx_num = pending_rexx_in = pending_rexx_out = 0;
for (i = 0; i < REXXSIZE; i++) sent_rexx_msg[i].msg = 0;
sent_rexx_id = 0;
}
void cleanup_amiga_rexx(void)
{
FreeARexx(handle);
}
void syms_of_amiga_rexx(void)
{
DEFVAR_BOOL ("amiga-arexx-initialized", &amiga_arexx_initialized,
"Set this to t when Emacs is ready to respond to ARexx messages.\n\
(ie C-\ X causes all pending ARexx messages to be answered)");
amiga_arexx_initialized = 0;
defsubr(&Samiga_arexx_send_command);
defsubr(&Samiga_arexx_reply);
defsubr(&Samiga_arexx_get_event);
defsubr(&Samiga_arexx_check_command);
defsubr(&Samiga_arexx_wait);
}